package com.example.websocketclusterspringbootstarter.aware;

import java.beans.Introspector;
import java.util.Collection;

import com.corundumstudio.socketio.SocketIOServer;
import org.springframework.beans.BeansException;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.example.websocketclusterspringbootstarter.annotation.EventClassName;
import com.example.websocketclusterspringbootstarter.annotation.EventHandlerName;
import com.example.websocketclusterspringbootstarter.event.BaseEvent;
import com.example.websocketclusterspringbootstarter.handler.EventHandler;
import com.example.websocketclusterspringbootstarter.helper.TransferHelper;
import com.example.websocketclusterspringbootstarter.utils.EventClassUtil;
import com.example.websocketclusterspringbootstarter.utils.EventHandlerUtil;

import lombok.extern.slf4j.Slf4j;

import javax.annotation.PostConstruct;

/**
 * 公共依赖初始化
 *
 * @author zhucc
 * @date 2022-03-08
 */
@Slf4j
public class CommonInitAware implements CommandLineRunner, ApplicationContextAware, SmartLifecycle {

    private volatile ApplicationContext applicationContext;

    private final static String         EVENT_NAME_SUFFIX = "Event";

    private final static String         EMPTY_STRING      = "";

    private volatile boolean            isRunning         = false;

    private SocketIOServer              socketIoServer;

    @PostConstruct
    public void initSocketServer() {
        // 从 ApplicationContext 获取 SocketIOServer bean
        this.socketIoServer = applicationContext.getBean(SocketIOServer.class);
    }

    @Override
    public void run(String... strings) {
        initHandler();
        initEventEntity();
    }

    public void initHandler() {
        Collection<EventHandler> values = this.applicationContext.getBeansOfType(EventHandler.class)
            .values();
        for (EventHandler eventHandler : values) {
            EventHandlerUtil.addHandler(
                eventHandler.getClass().getAnnotation(EventHandlerName.class).value(),
                eventHandler);
        }
    }

    public void initEventEntity() {
        Collection<BaseEvent> values = this.applicationContext.getBeansOfType(BaseEvent.class)
            .values();
        for (BaseEvent event : values) {
            EventClassName annotation = event.getClass().getAnnotation(EventClassName.class);
            //没有注解，或者注解上面的值是空（""）
            if (null == annotation || StringUtils.isEmpty(annotation.value())) {
                String simpleName = event.getClass().getSimpleName();
                if (simpleName.contains(EVENT_NAME_SUFFIX)) {
                    simpleName = simpleName.replace(EVENT_NAME_SUFFIX, EMPTY_STRING);
                }
                EventClassUtil.addEventClass(Introspector.decapitalize(simpleName),
                    event.getClass());
            } else {
                EventClassUtil.addEventClass(annotation.value(), event.getClass());
            }
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 启动 SocketIOServer
     */
    private void startSocketIoServer() {
        log.info("正在启动 SocketIOServer...");
        try {
            if (socketIoServer != null) {
                socketIoServer.start();
                log.info("SocketIOServer 启动成功，监听端口，监听endPoint: {}:{}",
                    socketIoServer.getConfiguration().getPort(),
                    socketIoServer.getConfiguration().getContext());
                isRunning = true;
            } else {
                log.warn("SocketIOServer 实例为空，无法启动");
            }
        } catch (Exception e) {
            log.error("SocketIOServer 启动失败", e);
            isRunning = false;
            throw new RuntimeException("SocketIOServer 启动失败", e);
        }
    }

    /**
     * 停止 SocketIOServer
     */
    private void stopSocketIoServer() {
        log.info("正在停止 SocketIOServer...");
        try {
            if (socketIoServer != null && isRunning) {
                socketIoServer.stop();
                log.info("SocketIOServer 停止成功");
            }
        } catch (Exception e) {
            log.error("SocketIOServer 停止失败", e);
        } finally {
            isRunning = false;
        }
    }

    // ============ SmartLifecycle 接口实现 ============

    @Override
    public void start() {
        if (!isRunning) {
            startSocketIoServer();
        }
    }

    @Override
    public void stop() {
        if (isRunning) {
            stopSocketIoServer();
        }
    }

    @Override
    public boolean isRunning() {
        return isRunning;
    }

    @Override
    public boolean isAutoStartup() {
        return true; // 设置为 true 表示自动启动
    }

    @Override
    public void stop(Runnable callback) {
        stop();
        callback.run(); // 通知 Spring 容器停止完成
    }

    @Override
    public int getPhase() {
        return 0; // 启动阶段的优先级
    }

}